/*******************************************************************************
 * Package: com.song.flowable.service.impl
 * Type:    ModelServiceImpl
 * Date:    2023-11-27 21:06
 *
 * Copyright (c) 2023 LTD All Rights Reserved.
 *
 * You may not use this file except in compliance with the License.
 *******************************************************************************/
package com.song.flowable.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.song.flowable.convert.ModelConvert;
import com.song.flowable.entity.ActDeModelDO;
import com.song.flowable.mapper.IActDeModelMapper;
import com.song.flowable.service.ModelService;
import com.song.flowable.dto.ModelPageReqDTO;
import com.song.flowable.vo.ModelVO;
import org.apache.commons.lang3.StringUtils;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * 功能描述：
 *
 * @author Songxianyang
 * @date 2023-11-27 21:06
 */
@Service
public class ModelServiceImpl implements ModelService {
    @Resource
    private IActDeModelMapper actDeModelMapper;

    @Resource
    private RepositoryService repositoryService;

    /**
     * 获得流程模型分页
     *
     * @param dto 分页查询
     * @return 流程模型分页
     */
    @Override
    public List<ModelVO> getModelPage(ModelPageReqDTO dto) {
        QueryWrapper<ActDeModelDO> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<ActDeModelDO> like = wrapper.lambda().eq(StringUtils.isNotBlank(dto.getKey()), ActDeModelDO::getId, dto.getKey())
                .like(StringUtils.isNotBlank(dto.getLikeName()), ActDeModelDO::getName, "%" + dto.getLikeName() + "%");

        List<ActDeModelDO> actDeModelDOS = actDeModelMapper.selectList(like);
        List<ModelVO> vos = ModelConvert.INSTANCE.toModelVOList(actDeModelDOS);
        return vos;
    }



    /**
     * 删除模型
     *
     * @param id 编号
     */
    @Override
    public Boolean deleteModel(String id) {
        actDeModelMapper.deleteById(id);
        return true;
    }

    /**
     * 修改模型部署的流程定义状态
     *
     * @param id    编号（1激活 2停止、挂起、暂停）
     * @param state 状态
     */
    @Override
    public String updateModelState(String id, Integer state) {
        // 校验流程model存在
        Model model = repositoryService.getModel(id);
        if (model == null) {
            throw new RuntimeException("流程模型不存在");
        }
        // 校验流程definition存在
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(model.getDeploymentId()).singleResult();
        if (definition == null) {
            throw new RuntimeException("流程定义不存在");
        }
        // 激活
        if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), state)) {
            repositoryService.activateProcessDefinitionById(id, false, null);
            return "修改模型部署的流程定义状态成功";
        }
        // 停止
        if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), state)) {
            // suspendProcessInstances = false，进行中的任务，不停止。
            // 原因：只要新的流程不允许发起即可，老流程继续可以执行。
            repositoryService.suspendProcessDefinitionById(id, false, null);
            return "修改模型部署的流程定义状态成功";
        }
        return "成功";
    }

    /**
     * 获得流程模块
     *
     * @param id 编号
     * @return ModelRespDTO
     */
    @Override
    public ModelVO getModel(String id) {
        ModelVO modelVO = ModelConvert.INSTANCE.toModelVO(actDeModelMapper.selectById(id));
        modelVO.setFlowXml(getXml(modelVO.getId()));
        return modelVO;
    }

    /**
     *
     * @param id 模型id
     * @return
     */
    private String getXml(String id) {
        // 拼接 bpmn XML
        byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
        return StrUtil.utf8Str(bpmnBytes);
    }
}
